<template>
  <p>单张/多张图片上传/多选图片上传</p>
  <div class="upload_box">
    <div class="imgshow_box" v-for="(item, index) in imgListArr" :key="index">
      <el-image :src="item" :preview-src-list="[item]" class="img_info"></el-image>
      <div class="mask" @click.stop="handleDelImg(index)">
        <span class="set_span" title="删除">
          <el-icon color="#fff" :size="14">
            <Delete />
          </el-icon>
        </span>
      </div>
    </div>
    <div class="selectFile" @click="startSelectFile" v-if="isOkUpload">
      <el-progress v-show="showProgress" type="circle" style="width: 90px; height: 90px" class="setprogress_my" :percentage="progresTent" :stroke-width="4" />
      <el-icon :size="28" v-show="!showProgress" color="#666">
        <Upload />
      </el-icon>
    </div>
    <input type="file" :multiple="multiple" @change="handleChange" class="file_input" />
  </div>

  <div class="tips_box">
    tips:文件大小限制2M,后缀：<span class="legaExts">{{ legaExts.toString() }};</span>
  </div>
</template>

<script setup>
import { ref, onMounted, defineProps, defineEmits, computed, watch } from 'vue';
import { uploadFn } from '../apis/upload';
import { ElMessage } from 'element-plus';
const limtSize = 1 * 1024 * 1024; //1M
const legaExts = ['.png', '.jpeg', '.jpg', '.gif', '.bmp', '.webp'];
// 接收父组件的props
const prop = defineProps({
  //图片集合
  imgList: {
    type: Array,
    default: () => []
  },
  //允许多选文件
  multiple: {
    type: Boolean,
    default: false
  },
  // 传文件限制个数 默认10张
  limit: {
    type: Number,
    default: 10
  }
});

const emit = defineEmits(['update:imgList']);

var showProgress = ref(false); //显示精度条还是上传按钮
var progresTent = ref(0); // 精度条控制样式

// 渲染完成才能拿到dom 放onMounted 周期里面
var fileInput; //代表选择文件的input dom
fileInput = document.querySelectorAll('.file_input');
onMounted(() => {
  fileInput = document.querySelectorAll('.file_input');
});

//初始化数据方式一 computed
var imgListArr = ref([]); //图片上传成功的数组
const ggArr = computed({
  get() {
    return prop.imgList.slice(0, prop.limit);
  },
  set(value) {
    emit('update:imgList', value);
  }
});
// console.log('ggArr',ggArr);
imgListArr.value = ggArr.value || []; //初始化图片集合 做回显更新操作

//初始化数据 方式二 watch
//只有在初始化的时候子组件需要对prop传来的变量进行监听，即监听只需要生效一次  不然会死循环
// watch(()=>prop.imgList,(newArr,oldArr)=>{
//   console.log('---',newArr,oldArr);
//   if(newArr&&newArr.length>0) imgListArr.value=newArr.slice(0,prop.limit);
//   else{
//     imgListArr.value=[];
//   }
// },{
//   deep:true,
//   immediate:true
// });
// limt限制上传个数的控制
const isOkUpload = computed(() => prop.limit >= imgListArr.value.length + 1);

// 选择文件点击事件 触发input 的选择行为
const startSelectFile = () => {
  // 如何没获取到input dom 不执行
  if (fileInput.length <= 0) return false;
  //每次选择前先清空input 之前选择的文件
  fileInput[0].value = null;
  // 调用input 选择文件行为
  fileInput[0].click();
};

// 选择结果变化 得到选择Files
// input 触发@change事件（值一变化立即执行）
const handleChange = (e) => {
  console.log('选择的文件 e.target.files', e.target.files);
  if (validateFile(Array.from(e.target.files))) {
    sendFile(e.target.files);
  }
};

//选择文件的校验 尺寸 后缀名
const validateFile = (files) => {
  //图片只要有一项大于规定尺寸 false
  if (files.some((ig) => ig.size > limtSize)) {
    ElMessage({
      message: '图片尺寸大了！',
      type: 'warning'
    });
    return false;
  }

  for (const item of files) {
    //后缀名 是否存在
    let name = item.name.toLowerCase(); //文件名转小写
    //name.endsWith(ig)  判断当前字符串是否是以另外一个给定的子字符串“结尾”的
    if (!legaExts.some((ig) => name.endsWith(ig))) {
      ElMessage({
        message: '后缀名不存在！',
        type: 'warning'
      });
      return false;
    }
  }

  return true;
};

// 上传图片
// FilesArr  代表选择的文件Files List
const sendFile = async (FilesArr) => {
  if (FilesArr.length <= 0) return false;

  for (const item of FilesArr) {
    let formData = new FormData();
    /*
       @prams formData.append(name, value, filename);
       @prams name 表示value中包含的数据对应的表单名称。
       @prams value 表示表单的值。可以是USVString 或 Blob (包括子类型，如 File)
       @prams filename 表示传给服务器的文件名称 Blob 对象的默认文件名是 "blob"。 File 对象的默认文件名是该文件的名称
      */
    formData.append('file', item, item.name);
    // 开始上传显示进度条
    showProgress.value = true;
    // let { data } = await uploadFn(formData, (procent) => {
    //   console.log(procent); //文件上传函数 自定义 callback 回调 返回上传进度
    //   progresTent.value = procent;
    // });
    await uploadFn(formData, (procent) => {
      console.log(procent); //文件上传函数 自定义 callback 回调 返回上传进度
      progresTent.value = procent;
    })
      .then((res) => {
        console.log('----', res);
        if (res.data.src && res.data) {
          imgListArr.value.push(res.data.src);
        } else {
          ElMessage({
            message: '文件上传失败！请重试',
            type: 'error'
          });
        }
      })
      .catch(() => {
        ElMessage({
          message: '文件上传失败！请重试',
          type: 'error'
        });
      })
      .finally(() => {
        // 成功失败隐藏进度条
        showProgress.value = false;
      });
  }
};

// 删除图片
const handleDelImg = (index) => {
  if (imgListArr.value.length === 0) return false;
  imgListArr.value.splice(index, 1);

  //   正常要后端删除 这里不需要先
  ElMessage({
    message: '删除成功！',
    type: 'success'
  });

  console.log(imgListArr.value);
  emit('update:imgList', imgListArr.value);
};
</script>

<style lang="scss" scoped>
.tips_box {
  font-size: 14px;
  color: #6666;
  .legaExts {
    color: red;
  }
}
.upload_box {
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;

  .file_input {
    display: none;
  }

  .selectFile {
    width: 100px;
    height: 100px;
    margin: 10px;
    border: 1px dashed #a49a9a;
    border-radius: 2px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;

    :deep(.el-progress-circle) {
      width: 90px !important;
      height: 90px !important;
    }

    &:hover {
      background-color: #f4ecec;
    }
  }

  .imgshow_box {
    width: 100px;
    height: 100px;
    margin: 10px;
    border-radius: 2px;
    overflow: hidden;
    position: relative;

    .img_info {
      width: 100%;
      height: 100%;

      // object-fit: contain;
    }

    .mask {
      opacity: 0;
      position: absolute;
      top: 0;
      right: 0px;
      width: 28px;
      height: 28px;
      background-color: rgba(0, 0, 0, 0.5);
      transition: all 0.3s;
      border-bottom-left-radius: 30px;
      overflow: hidden;
      display: flex;
      justify-content: center;
      align-items: center;

      .set_span {
        transform: translateX(2px);
      }
    }

    &:hover .mask {
      opacity: 1;
      cursor: pointer;
    }
  }
}
</style>
